#pragma once

#include <iostream>
#include <pthread.h>
#include <queue>
#include "Protocol.hpp"

typedef void (*handler_t)(int);
class Task{
    private:
        int sock;
        handler_t handler;
    public:
        Task(int sk):sock(sk),handler(Entry::HandlerHttp)
        {}
        void Run()
        {
            handler(sock);
        }
        ~Task()
        {}

};
class ThreadPool
{
    private:
        std::queue<Task*> q;
        int num;//表示线程个数
        pthread_mutex_t lock;//锁
        pthread_cond_t cond;//条件变量
    public:
        ThreadPool(int n = 4):num(n)
        {}
        void LockQueue()
        {
            pthread_mutex_lock(&lock);
        }
        void UnlockQueue()
        {
            pthread_mutex_unlock(&lock);
        }
        bool IsEmpty()
        {
            return q.size() == 0;
        }
        void ThreadWait()
        {
            pthread_cond_wait(&cond,&lock);
        }
        void ThreadWakeup()
        {
            pthread_cond_signal(&cond);
        }

        static void *Routine(void *args)//若不是静态则会多出一个this指针参数
        {
            //因为被声明了static，则该函数就没有了自带的this指针，所以需要用参数传进去
            ThreadPool *tp = (ThreadPool*)args;
            tp->LockQueue();
            while(tp->IsEmpty())
            {
                tp->ThreadWait();//没任务则线程休眠
            }
            Task *tk = tp->PopTask();//从任务队列拿任务
            tp->UnlockQueue();
            tk->Run();//拿到后执行任务
            delete tk;//执行完该任务后将任务删除
            //TODO
        
        void InitThreadPool()
        {
            pthread_mutex_init(&lock,nullptr);
            pthread_cond_init(&cond,nullptr);
            pthread_t tid;
            for(auto i = 0;i < num;i++)
            {
                pthread_create(&tid,nullptr,Routine,this);
                pthread_detach(tid);
            }
        }
        void PushTask(Task *tk)
        {
            LockQueue();
            q.push(tk);
            UnlockQueue();
            ThreadWakeup();
        }
        Task *PopTask()
        {
            Task *tk = q.front();
            q.pop();
            return tk;
        }
        ~ThreadPool()
        {
            pthread_mutex_destroy(&lock);
            pthread_cond_destroy(&cond);
        }
};
